package com.df.tools.handler.impl;

import com.df.tools.config.ConfigProperties;
import com.df.tools.handler.IHandler;
import com.df.tools.msg.MsgDefinition;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 后端代码生成处理器
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class BakendHandler implements IHandler {

    private final ConfigProperties configProperties;

    @Override
    public boolean canHandle() {
        return true;
    }

    @Override
    public void handle(List<MsgDefinition> msgDefinitions) throws Exception {
        System.out.println("================生成后端代码===================");
        List<MsgDefinition> bakendMsgDefinitions = msgDefinitions.stream().filter(m -> m.getType().equals(configProperties.getBakend().getMsgType())).collect(Collectors.toList());

        List<String> allMsgPackage = bakendMsgDefinitions.stream().map(def -> def.getMsgFullPackage()).distinct().collect(Collectors.toList());
        //筛选C2S类型的消息
//        System.out.println("后端代码生成处理器,处理消息：" + bakendMsgDefinitions);
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_31);
        // Specify the source where the template files come from. Here I set a
        // plain directory for it, but non-file-system sources are possible too:
        String path = Thread.currentThread().getContextClassLoader().getResource("templates/bakend").getPath();
        cfg.setDirectoryForTemplateLoading(new File(path));
        cfg.setDefaultEncoding("UTF-8");
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

        Map<String, Object> root = new HashMap<>();
        root.put("msgDefinitions", msgDefinitions);
        generatorMsgManager(cfg, root,allMsgPackage);
        generatorMsgScript(cfg, root, bakendMsgDefinitions);
        //msgScriptManager不用生成，会在游戏服务器启动的时候进行加载，因为这些脚本在开发环境会使用到热更新
    }

    private void generatorMsgScript(Configuration cfg, Map<String, Object> root, List<MsgDefinition> bakendMsgDefinitions) throws Exception {
        String scriptPath = configProperties.getBakend().getScriptPath();
        if (!scriptPath.endsWith("\\") && !scriptPath.endsWith("/")) {
            scriptPath = scriptPath + File.separator;
        }

        String scriptRootPackage = configProperties.getBakend().getScriptRootPackage();
        Template temp = cfg.getTemplate("C2S_SyncPositionScript.ftl");
        for (MsgDefinition bakendMsgDefinition : bakendMsgDefinitions) {
            String nowFilePath = scriptPath + bakendMsgDefinition.getPackage_name() + File.separator + bakendMsgDefinition.getName() + "Script.java";
            //先检查文件是否存在，存在则跳过，防止把写过的代码给冲掉了
            //当前脚本所在包
            String nowScriptPackage = scriptRootPackage + "." + bakendMsgDefinition.getPackage_name();
            root.put("nowScriptPackage", nowScriptPackage);
            String nowMsgPackage = configProperties.getBakend().getMsgPackage() + "." + bakendMsgDefinition.getJava_outer_classname();
            root.put("nowMsgPackage", nowMsgPackage);
            root.put("nowMsgDefinition", bakendMsgDefinition);
            File file = new File(nowFilePath);
            if (!file.exists()) {
                File parentFile = file.getParentFile();
                if (!parentFile.exists()) {
                    parentFile.mkdir();
                }
                file.createNewFile();
                FileWriter writer = new FileWriter(file);
//            Writer writer = new OutputStreamWriter(System.out);
                temp.process(root, writer);
                log.info(bakendMsgDefinition.getName() + "Script.java 生成成功！:" + nowFilePath);
                continue;
            }
//            log.warn(bakendMsgDefinition.getName()+"Script.java 已经存在！:"+nowFilePath);
//            break;
        }


    }

    private void generatorMsgManager(Configuration cfg, Map<String, Object> root, List<String> allMsgPackage) throws Exception {
        root.put("allMsgPackage", allMsgPackage);
        root.put("msgRegisterPackage", configProperties.getBakend().getMsgRegisterPackage());
        Template temp = cfg.getTemplate("MsgRegister.ftl");
        Writer writer = new FileWriter(configProperties.getBakend().getMsgRegisterPath());
//        Writer out = new OutputStreamWriter(System.out);
        temp.process(root, writer);
        log.info("MsgRegister.java 生成成功！:" + configProperties.getBakend().getMsgRegisterPath());
    }
}
